package benchmark;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;


import tools.SizedObjects.*;

public class TaskFalseSharing extends AbstractTask {
	/*
	 * args:
	 * 0. element size
	 * 1. thread number
	 * 2. iteration time
	 */
	public TaskFalseSharing(List<String> args) {
		super(args);
		elementType = args.get(0);
		elementSize = Integer.parseInt(args.get(1));
		threadNumber = Integer.parseInt(args.get(2));
		iterationTime = Long.parseLong(args.get(3));
		int arraySize = threadNumber;
		
		if (elementType.equals("hard")) {
			switch(elementSize) {
			case 16:
				workingArrayHard16 = new Object16Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard16[i] = new Object16Hard();
				}
				break;
			case 24:
				workingArrayHard24 = new Object24Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard24[i] = new Object24Hard();
				}
				break;
			case 32:
				workingArrayHard32 = new Object32Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard32[i] = new Object32Hard();
				}
				break;
			case 40:
				workingArrayHard40 = new Object40Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard40[i] = new Object40Hard();
				}
				break;
			case 48:
				workingArrayHard48 = new Object48Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard48[i] = new Object48Hard();
				}
				break;
			case 56:
				workingArrayHard56 = new Object56Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard56[i] = new Object56Hard();
				}
				break;
			case 64:
				workingArrayHard64 = new Object64Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard64[i] = new Object64Hard();
				}
				break;
			case 72:
				workingArrayHard72 = new Object72Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard72[i] = new Object72Hard();
				}
				break;
			case 80:
				workingArrayHard80 = new Object80Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard80[i] = new Object80Hard();
				}
				break;
			case 88:
				workingArrayHard88 = new Object88Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard88[i] = new Object88Hard();
				}
				break;
			case 96:
				workingArrayHard96 = new Object96Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard96[i] = new Object96Hard();
				}
				break;
			case 104:
				workingArrayHard104 = new Object104Hard[arraySize];
				for(int i = 0; i < arraySize; i++) {
					workingArrayHard104[i] = new Object104Hard();
				}
				break;
				
			default:
				break;
			}
		} else {
			String className = String.format("tools.SizedObjects$Object%d", elementSize);
			try {
				Class<?> c = Class.forName(className);
				workingArray = (Object16[]) Array.newInstance(c, arraySize);
				for (int i = 0; i < arraySize; i++) {
					workingArray[i] = (Object16) c.newInstance();
					// initial value
					//workingArray[i].value = i;
				}
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

//		String className = String.format("tools.SizedObjects$Object%d", elementSize);
//		if(elementType.equals("hard")) {
//			className += "Hard";
//		}
//		try {
//			Class<?> c = Class.forName(className);
//			workingArray = (Object16[]) Array.newInstance(c, arraySize);
//			for (int i = 0; i < arraySize; i++) {
//				workingArray[i] = (Object16) c.newInstance();
//				// initial value
//				//workingArray[i].value = i;
//			}
//		} catch (ClassNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (InstantiationException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (IllegalAccessException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}

	}

	public TaskFalseSharing(Integer threadID) {
		super(threadID);
	}

	private static String elementType;
	private static long iterationTime;
	private static int elementSize;	
	
	protected static Object16[] workingArray;
	
	
	protected static Object16Hard[] workingArrayHard16 = new Object16Hard[threadNumber];
	protected static Object24Hard[] workingArrayHard24 = new Object24Hard[threadNumber];
	protected static Object32Hard[] workingArrayHard32 = new Object32Hard[threadNumber];
	protected static Object40Hard[] workingArrayHard40 = new Object40Hard[threadNumber];
	protected static Object48Hard[] workingArrayHard48 = new Object48Hard[threadNumber];
	protected static Object56Hard[] workingArrayHard56 = new Object56Hard[threadNumber];
	protected static Object64Hard[] workingArrayHard64 = new Object64Hard[threadNumber];
	protected static Object72Hard[] workingArrayHard72 = new Object72Hard[threadNumber];
	protected static Object80Hard[] workingArrayHard80 = new Object80Hard[threadNumber];
	protected static Object88Hard[] workingArrayHard88 = new Object88Hard[threadNumber];
	protected static Object96Hard[] workingArrayHard96 = new Object96Hard[threadNumber];
	protected static Object104Hard[] workingArrayHard104 = new Object104Hard[threadNumber];
	

	
	@Override
	public void run() {

		long i = iterationTime + 1;
		long timeStart = System.nanoTime();
		

		if(elementType.equals("hard")) {
			switch(elementSize) {
			case 16:
				while(0 != --i) {
					workingArrayHard16[this.threadID].value = (int)i;
				}
				break;
			case 24:
				while(0 != --i) {
					workingArrayHard24[this.threadID].value = (int)i;
				}
				break;
			case 32:
				while(0 != --i) {
					workingArrayHard32[this.threadID].value = (int)i;
				}
				break;
			case 40:
				while(0 != --i) {
					workingArrayHard40[this.threadID].value = (int)i;
				}
				break;
			case 48:
				while(0 != --i) {
					workingArrayHard48[this.threadID].value = (int)i;
				}
				break;
			case 56:
				while(0 != --i) {
					workingArrayHard56[this.threadID].value = (int)i;
				}
				break;
			case 64:
				while(0 != --i) {
					workingArrayHard64[this.threadID].value = (int)i;
				}
				break;
			case 72:
				while(0 != --i) {
					workingArrayHard72[this.threadID].value = (int)i;
				}
				break;
			case 80:
				while(0 != --i) {
					workingArrayHard80[this.threadID].value = (int)i;
				}
				break;
			case 88:
				while(0 != --i) {
					workingArrayHard88[this.threadID].value = (int)i;
				}
				break;
			case 96:
				while(0 != --i) {
					workingArrayHard96[this.threadID].value = (int)i;
				}
				break;
			case 104:
				while(0 != --i) {
					workingArrayHard104[this.threadID].value = (int)i;
				}
				break;
			default:
				break;
			}
		} else {
			while(0 != --i) {
				workingArray[this.threadID].value = (int)i;
			}
		}

//		while(0 != --i) {
//			workingArray[this.threadID].value = (int)i;
//		}
		
		duration = System.nanoTime() - timeStart;
		/*
		if(workingArrayReal != null) {
			long timeStart = System.nanoTime();

			for (int i = 0; i < iterationTime; i++) {
				workingArrayReal[this.threadID].value = i;
			}
			duration = System.nanoTime() - timeStart;
		} else {
			long timeStart = System.nanoTime();

			for (int i = 0; i < iterationTime; i++) {
				workingArray[this.threadID].value = i;
			}
			duration = System.nanoTime() - timeStart;
		}
		*/

	}

	
	public static void main(String[] args) throws Exception {
		String et = "soft";
		int esi = 64;
		String es = Integer.toString(esi);
		String tn = "2";
		String it = "50000000";
		List<String> arg = new ArrayList<String>();
		arg.add(et);
		arg.add(es);
		arg.add(tn);
		arg.add(it);
		
//		TaskFalseSharing task = new TaskFalseSharing(arg);

		for (int i = 16; i <= 104; i += 8) {
			arg.set(1, Integer.toString(i));
			TaskFalseSharing task = new TaskFalseSharing(arg);
			long result = task.compute();
			System.out.format("%d: %d\n", i, result);
		}
		
//		String result = task.compute(1);
//		long result = task.compute();
//		System.out.println(result);
		
	}

}
